package com.poi.demo.parser;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.xwpf.usermodel.*;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Objects;

/**
 * <p>Word图片解析器</p>
 *
 * @author Allen Yang
 * @datetime 2021/11/18 14:53
 */
@Setter
@Getter
@Slf4j
public class WordPictureParser extends WordContentParser {

    //模板中${type}下标${index}的图片不存在替换值---是否抛异常
    private boolean throwException;

    private List<PictureReplace> pictureReplaces;

    private int picIndexOfParagraph;

    private void setPicIndexOfParagraph(int picIndexOfParagraph) {
        this.picIndexOfParagraph = picIndexOfParagraph;
    }

    public WordPictureParser(InputStream in, List<PictureReplace> pictureReplaces) {
        super(in);
        this.pictureReplaces = pictureReplaces;
        this.throwException = true;
        this.picIndexOfParagraph = 0;
    }

    public WordPictureParser(XWPFDocument doc, List<PictureReplace> pictureReplaces) {
        super(doc);
        this.pictureReplaces = pictureReplaces;
        this.throwException = true;
        this.picIndexOfParagraph = 0;
    }

    public WordPictureParser(InputStream in) {
        super(in);
        this.throwException = true;
        this.picIndexOfParagraph = 0;
    }

    public WordPictureParser(XWPFDocument doc) {
        super(doc);
        this.throwException = true;
        this.picIndexOfParagraph = 0;
    }

    public WordPictureParser(String path) {
        super(path);
        this.throwException = true;
        this.picIndexOfParagraph = 0;
    }

    @Setter
    @Getter
    public static class PictureReplace {
        //内容类型，1 段落图片 、 2 表格图片
        private int type;
        public static final int TYPE_PARAGRAPH = 1;
        public static final int TYPE_TABLE = 2;
        //图片在模板的下标，Word文档段落和表格从左到右算起，段落和表格单独分开计数，0开始
        private int index;
        //图片流数据
        private InputStream pictureData;
        //图片类型
        private int pictureType;

        public PictureReplace() {
            this.type = TYPE_PARAGRAPH;
            this.pictureType = XWPFDocument.PICTURE_TYPE_PNG;
        }
    }

    public static InputStream loadPictureData(String path) {
        try {
            return new FileInputStream(path);
        } catch (FileNotFoundException e) {
            log.error("FileNotFoundException->{}", path);
            return null;
        }
    }

    @Override
    public XWPFDocument replace() {
        if (Objects.isNull(getDoc())) {
            throw new RuntimeException(ERR_MSG_DOC_NOT_LOADED);
        }
        if (CollectionUtils.isEmpty(pictureReplaces)) {
            throw new RuntimeException(ERR_MSG_PARAM_NOT_INITIALIZED);
        }

        picIndexOfParagraph = 0;
        pictureReplace(PictureReplace.TYPE_PARAGRAPH, getDoc().getParagraphs());

        picIndexOfParagraph = 0;
        getDoc().getTables().forEach(xwpfTable -> {
            xwpfTable.getRows().forEach(row -> {
                row.getTableCells().forEach(xwpfTableCell -> {
                    pictureReplace(PictureReplace.TYPE_TABLE, xwpfTableCell.getParagraphs());
                });
            });
        });

        pictureReplaces.forEach(pictureReplace -> {
            if (Objects.nonNull(pictureReplace.getPictureData())) {
                try {
                    pictureReplace.getPictureData().close();
                } catch (IOException e) {
                    log.error("{} {}", pictureReplace, e.getMessage());
                }
            }
        });

        return getDoc();
    }

    private void pictureReplace(int type, List<XWPFParagraph> xwpfParagraphs) {
        int runIndex = 0;
        for (int i = 0, size = xwpfParagraphs.size(); i < size; i++) {
            XWPFParagraph xwpfParagraph = xwpfParagraphs.get(i);
            List<XWPFRun> runs = xwpfParagraph.getRuns();
            for (int j = 0, size2 = runs.size(); j < size2; j++) {
                List<XWPFPicture> xwpfPictures = runs.get(j).getEmbeddedPictures();
                if (CollectionUtils.isNotEmpty(xwpfPictures)) {
                    PictureReplace pictureReplace = null;
                    runIndex = j;
                    XWPFRun newXWPFRun = xwpfParagraph.createRun();
                    for (int k = 0, size3 = xwpfPictures.size(); k < size3; k++) {
                        int width = (int) xwpfPictures.get(k).getCTPicture().getSpPr().getXfrm().getExt().getCx();
                        int height = (int) xwpfPictures.get(k).getCTPicture().getSpPr().getXfrm().getExt().getCy();
                        String filename = xwpfPictures.get(k).getPictureData().getFileName();
                        int finalPicIndexOfParagraph = picIndexOfParagraph;
                        pictureReplace = pictureReplaces.stream().filter(o -> type == o.getType()).filter(o -> o.getIndex() == finalPicIndexOfParagraph).findFirst().orElse(null);
                        if (Objects.nonNull(pictureReplace)) {
                            try {
                                newXWPFRun.addPicture(pictureReplace.getPictureData(), pictureReplace.getPictureType(), filename, width, height);
                            } catch (Exception e) {
                                log.error("{}；{}", ERR_MSG_PIC_NOT_ADD.replace("${index}", String.valueOf(finalPicIndexOfParagraph)), e.getMessage());
                                throw new RuntimeException(ERR_MSG_PIC_NOT_ADD.replace("${index}", String.valueOf(finalPicIndexOfParagraph)));
                            }
                        } else {
                            if (throwException) {
                                throw new RuntimeException(ERR_MSG_PIC_NOT_EXIST.replace("${type}", type == PictureReplace.TYPE_PARAGRAPH ? "段落图片" : "表格图片").replace("${index}", String.valueOf(finalPicIndexOfParagraph)));
                            }
                        }
                        picIndexOfParagraph++;
                        //log.info("{}下标{}{}", type == PictureReplace.TYPE_PARAGRAPH ? "段落图片" : "表格图片", picIndexOfParagraph, Objects.nonNull(pictureReplace) ? "已替换" : "不存在");
                    }
                    if (Objects.nonNull(pictureReplace)) {
                        xwpfParagraph.removeRun(runIndex);
                        xwpfParagraph.addRun(newXWPFRun);
                    }
                }
            }
        }
    }
}
